package org.example;

// 项目结构概览：
// GameMain.java          - 主入口
// ui/                    - 界面组件包
// managers/              - 管理类包
// models/                - 数据模型包
// patterns/              - 设计模式实现包
// utils/                 - 工具类包

import javax.swing.*;
import javax.swing.Timer;
import java.awt.*;
import java.awt.List;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.*;

// 1. 主入口类
public class GameMain {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            GameEngine engine = GameEngine.getInstance();
            engine.initialize();
            engine.showMainMenu();
        });
    }
}

// 2. 单例模式 - 游戏引擎核心
class GameEngine {
    private static GameEngine instance;
    private JFrame mainFrame;
    private CardLayout cardLayout;
    private JPanel mainPanel;
    private PlayerData playerData;

    private GameEngine() {}

    public static synchronized GameEngine getInstance() {
        if (instance == null) {
            instance = new GameEngine();
        }
        return instance;
    }

    public void initialize() {
        mainFrame = new JFrame("Code Rebirth: 系统觉醒");
        mainFrame.setSize(1280, 720);
        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        cardLayout = new CardLayout();
        mainPanel = new JPanel(cardLayout);

        // 初始化所有界面
        mainPanel.add(new MainMenuPanel(), "MAIN_MENU");
        mainPanel.add(new CutscenePanel(1), "CUTSCENE_1");
        mainPanel.add(new RepairPanel(), "REPAIR");
        // 添加其他界面...

        mainFrame.add(mainPanel);
        mainFrame.setVisible(true);
    }

    public void switchScreen(String screenName) {
        cardLayout.show(mainPanel, screenName);
        mainFrame.revalidate();
        mainFrame.repaint();
    }

    // 其他游戏控制方法...
}

// 3. 主菜单界面（工厂模式 + 状态模式）
class MainMenuPanel extends JPanel {
    public MainMenuPanel() {
        setLayout(new BorderLayout());
        setBackground(Color.BLACK);

        // 动态标题
        JLabel titleLabel = new JLabel("Code Rebirth: 系统觉醒");
        titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 48));

        // 渐变动画
        Timer gradientTimer = new Timer(50, e -> repaint());
        gradientTimer.start();

        // 按钮面板
        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS));
        buttonPanel.setOpaque(false);

        JButton startBtn = new JButton("开始游戏");
        JButton loadBtn = new JButton("加载存档");
        JButton exitBtn = new JButton("退出游戏");

        // 按钮样式
        Arrays.asList(startBtn, loadBtn, exitBtn).forEach(btn -> {
            btn.setForeground(Color.WHITE);
            btn.setBackground(new Color(0, 0, 255, 100));
            btn.setFont(new Font("宋体", Font.PLAIN, 24));
            btn.addActionListener(this::handleButtonClick);
        });

        buttonPanel.add(Box.createVerticalGlue());
        buttonPanel.add(startBtn);
        buttonPanel.add(Box.createVerticalStrut(20));
        buttonPanel.add(loadBtn);
        buttonPanel.add(Box.createVerticalStrut(20));
        buttonPanel.add(exitBtn);
        buttonPanel.add(Box.createVerticalGlue());

        add(buttonPanel, BorderLayout.WEST);
    }

    private void handleButtonClick(ActionEvent e) {
        String command = ((JButton)e.getSource()).getText();
        switch (command) {
            case "开始游戏":
                GameEngine.getInstance().switchScreen("CUTSCENE_1");
                break;
            case "加载存档":
                ArchiveManager.getInstance().loadGame();
                break;
            case "退出游戏":
                System.exit(0);
        }
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;

        // 创建动态渐变
        GradientPaint gradient = new GradientPaint(
                0, getHeight()/2, Color.BLACK,
                getWidth(), getHeight()/2, Color.BLUE
        );
        g2d.setPaint(gradient);
        g2d.fillRect(0, 0, getWidth(), getHeight());
    }
}

// 4. 过场动画界面（状态模式）
class CutscenePanel extends JPanel {
    private int sceneId;
    private Timer sceneTimer;
    private int currentImageIndex = 0;
    private List<Image> images = new ArrayList<>();
    // 在RepairPanel中添加
    private List<CodeQuestion> questionBank;

    private void loadQuestions() {
        questionBank = new ArrayList<>();
        // 从JSON文件加载题目
        questionBank.add(new CodeQuestion(
                "实现单例模式",
                "public class Singleton { ... }",
                "Singleton.class"
        ));
    }

    private static class CodeQuestion {
        private String description;
        private String referenceCode;
        private String className;

        // 构造方法和getter
    }

    public CutscenePanel(int sceneId) {
        this.sceneId = sceneId;
        setLayout(new BorderLayout());
        loadSceneResources();
        initInteraction();
    }

    private void loadSceneResources() {
        // 根据sceneId加载图片资源
        // 示例代码使用颜色块代替实际图片
        images.add(createColorImage(Color.RED));
        images.add(createColorImage(Color.BLUE));
    }

    private Image createColorImage(Color color) {
        BufferedImage img = new BufferedImage(1280, 720, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = img.createGraphics();
        g.setColor(color);
        g.fillRect(0, 0, 1280, 720);
        g.dispose();
        return img;
    }

    private void initInteraction() {
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                advanceScene();
            }
        });

        sceneTimer = new Timer(10000, e -> advanceScene());
        sceneTimer.setRepeats(false);
        sceneTimer.start();
    }

    private void advanceScene() {
        if (++currentImageIndex < images.size()) {
            repaint();
            sceneTimer.restart();
        } else {
            GameEngine.getInstance().switchScreen("REPAIR");
        }
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (currentImageIndex < images.size()) {
            g.drawImage(images.get(currentImageIndex), 0, 0, null);
        }
    }
}

// 5. 修复界面（观察者模式 + 状态模式）
class RepairPanel extends JPanel {
    private JProgressBar progressBar;
    private int currentScore = 0;
    private int repairProgress = 0;
    private JLabel scoreLabel;
    private JTextArea questionArea;
    private JTextField answerField;

    public RepairPanel() {
        setLayout(new BorderLayout());
        setBackground(Color.BLACK);

        initQuestionArea();
        initAnswerField();
        initControlPanel();
        initProgressBar();
        // 使用示例（在RepairPanel中）：
        GameEngine.getInstance().updatePlayerData(data -> {
            data.addScore(20);
            data.updateRepairProgress(data.getRepairProgress() + 20);
        });
    }

    private void initQuestionArea() {
        questionArea = new JTextArea();
        questionArea.setEditable(false);
        questionArea.setForeground(Color.WHITE);
        questionArea.setBackground(new Color(0, 0, 255, 102));
        questionArea.setFont(new Font("等线", Font.BOLD, 20));
        questionArea.setText(generateQuestion());
        add(questionArea, BorderLayout.NORTH);
    }

    private void initAnswerField() {
        answerField = new JTextField();
        answerField.setForeground(new Color(0, 255, 0));
        answerField.setBackground(Color.BLACK);
        answerField.setFont(new Font("Consolas", Font.PLAIN, 24));
        add(answerField, BorderLayout.CENTER);
    }

    private void initControlPanel() {
        JPanel panel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        panel.setOpaque(false);

        scoreLabel = new JLabel("积分: 0");
        scoreLabel.setForeground(Color.WHITE);

        JButton hintBtn = new JButton("提示（10积分）");
        JButton saveBtn = new JButton("保存进度");
        JButton submitBtn = new JButton("提交");

        // 按钮样式
        Arrays.asList(hintBtn, saveBtn, submitBtn).forEach(btn -> {
            btn.setForeground(Color.WHITE);
            btn.setBackground(new Color(0, 0, 255, 100));
        });

        hintBtn.addActionListener(e -> showHint());
        saveBtn.addActionListener(e -> saveProgress());
        submitBtn.addActionListener(e -> checkAnswer());

        panel.add(scoreLabel);
        panel.add(hintBtn);
        panel.add(saveBtn);
        panel.add(submitBtn);
        add(panel, BorderLayout.SOUTH);
    }

    private void initProgressBar() {
        progressBar = new JProgressBar(0, 100);
        progressBar.setStringPainted(true);
        progressBar.setForeground(Color.BLUE);
        progressBar.setBackground(Color.DARK_GRAY);
        add(progressBar, BorderLayout.NORTH);
    }

    private String generateQuestion() {
        // 实际开发应从题库随机选取
        return "请写出Java中单例模式的实现代码：";
    }

    private void showHint() {
        if (currentScore >= 10) {
            currentScore -= 10;
            updateScore();
            JOptionPane.showMessageDialog(this, "提示内容...");
        } else {
            JOptionPane.showMessageDialog(this, "积分不足！");
        }
    }

    private void saveProgress() {
        ArchiveManager.getInstance().saveGame(
                new GameState(repairProgress, currentScore)
        );
    }

    private void checkAnswer() {
        String answer = answerField.getText().trim();
        // 实际应实现答案验证逻辑
        boolean isCorrect = validateAnswer(answer);

        if (isCorrect) {
            currentScore += 20;
            repairProgress += 20;
            updateProgress();
            updateScore();

            if (repairProgress >= 100) {
                completeRepair();
            } else {
                nextQuestion();
            }
        } else {
            GameEngine.getInstance().switchScreen("ALERT");
        }
    }

    private boolean validateAnswer(String answer) {
        // 示例验证逻辑
        return answer.contains("static") && answer.contains("getInstance()");
    }

    private void updateScore() {
        scoreLabel.setText("积分: " + currentScore);
    }

    private void updateProgress() {
        progressBar.setValue(repairProgress);
    }

    private void nextQuestion() {
        questionArea.setText(generateQuestion());
        answerField.setText("");
    }

    private void completeRepair() {
        // 进入后续界面逻辑
    }
}

// 6. 存档管理器（单例模式）
class ArchiveManager {
    private static ArchiveManager instance;
    private static final String SAVE_FILE = "game.sav";

    private ArchiveManager() {}

    public static synchronized ArchiveManager getInstance() {
        if (instance == null) {
            instance = new ArchiveManager();
        }
        return instance;
    }

    public void saveGame(GameState state) {
        try (ObjectOutputStream oos = new ObjectOutputStream(
                new FileOutputStream(SAVE_FILE))) {
            oos.writeObject(state);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public GameState loadGame() {
        try (ObjectInputStream ois = new ObjectInputStream(
                new FileInputStream(SAVE_FILE))) {
            return (GameState) ois.readObject();
        } catch (IOException | ClassNotFoundException ex) {
            return new GameState(0, 0);
        }
    }
}

// 7. 数据模型
class GameState implements Serializable {
    private int repairProgress;
    private int currentScore;

    public GameState(int progress, int score) {
        this.repairProgress = progress;
        this.currentScore = score;
    }

    // Getters and Setters...
}

// 8. 警报界面（装饰器模式）
class AlertPanel extends JPanel {
    public AlertPanel() {
        setLayout(new BorderLayout());
        setBackground(Color.BLACK);

        JLabel warningIcon = new JLabel(new ImageIcon(createWarningIcon()));
        warningIcon.setHorizontalAlignment(SwingConstants.CENTER);

        add(warningIcon, BorderLayout.CENTER);
        add(createMessagePanel(), BorderLayout.SOUTH);
    }

    private Image createWarningIcon() {
        BufferedImage img = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = img.createGraphics();

        // 绘制警告三角形
        g2d.setColor(Color.RED);
        g2d.setStroke(new BasicStroke(5));
        Polygon triangle = new Polygon();
        triangle.addPoint(100, 0);
        triangle.addPoint(200, 200);
        triangle.addPoint(0, 200);
        g2d.drawPolygon(triangle);

        // 绘制感叹号
        g2d.fillRect(95, 50, 10, 80);
        g2d.fillOval(90, 140, 20, 20);

        g2d.dispose();
        return img;
    }

    private JPanel createMessagePanel() {
        JPanel panel = new JPanel();
        panel.setOpaque(false);

        JLabel message = new JLabel("检测到异常操作！");
        message.setForeground(Color.RED);
        message.setFont(new Font("黑体", Font.BOLD, 32));

        panel.add(message);
        return panel;
    }
}

// 9. 商城界面（装饰器模式）
class ShopPanel extends JPanel {
    public ShopPanel() {
        setLayout(new GridLayout(3, 2, 20, 20));
        setBackground(Color.BLACK);

        add(createItemPanel("皮肤1", 100));
        add(createItemPanel("皮肤2", 200));
        add(createItemPanel("武器1", 150));
        // 添加更多商品...
    }

    private JPanel createItemPanel(String itemName, int price) {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBackground(new Color(30, 30, 30));

        JLabel nameLabel = new JLabel(itemName);
        JLabel priceLabel = new JLabel(price + "积分");
        JButton buyBtn = new JButton("购买");

        // 样式设置
        nameLabel.setForeground(Color.WHITE);
        priceLabel.setForeground(Color.YELLOW);
        buyBtn.setBackground(Color.GREEN);

        panel.add(nameLabel, BorderLayout.NORTH);
        panel.add(priceLabel, BorderLayout.CENTER);
        panel.add(buyBtn, BorderLayout.SOUTH);

        return panel;
    }
}
// 皮肤管理器
class SkinManager {
    private Map<String, Skin> skins = new HashMap<>();

    public void loadSkins() {
        skins.put("default", new Skin("默认", Color.BLUE));
        skins.put("hacker", new Skin("黑客", Color.GREEN));
    }


    // 在界面中使用
    public void applySkin(Skin skin) {
        questionArea.setBackground(skin.getBgColor());
        // 更新其他界面元素颜色
    }
}
// 添加在线排行榜
class Leaderboard {
    public void submitScore(String player, int score) {
        // 调用API提交分数
    }

    public List<ScoreEntry> getTopScores() {
        // 从服务器获取数据
        return new ArrayList<>();
    }
}
class SoundManager {
    public void playSound(String type) {
        switch (type) {
            case "SUCCESS":
                // 播放成功音效
                break;
            case "ERROR":
                // 播放错误音效
                break;
        }
    }
}
// PlayerData.java

class PlayerData implements Serializable {
    // 序列化版本号
    private static final long serialVersionUID = 1L;

    // 玩家基础数据
    private int score;                   // 当前积分
    private int repairProgress;          // 修复进度百分比
    private int currentCheckpoint;       // 当前存档点编号
    private String currentSkin;          // 当前使用皮肤ID
    private String currentEquipment;     // 当前装备ID

    // 玩家资产
    private Set<String> unlockedSkins = new HashSet<>();     // 已解锁皮肤
    private Set<String> ownedEquipments = new HashSet<>();   // 已拥有装备
    private List<String> inventory = new ArrayList<>();      // 道具库存

    // 游戏进度相关
    private Map<Integer, GameState> savePoints = new HashMap<>(); // 存档点数据
    private transient boolean modified;  // 数据修改标记（不序列化）

    public PlayerData() {
        // 初始化默认值
        this.score = 0;
        this.repairProgress = 0;
        this.currentCheckpoint = 1;
        this.currentSkin = "default";
        this.currentEquipment = "none";

        // 初始解锁默认皮肤
        unlockedSkins.add("default");
    }

    // region 积分操作方法
    public void addScore(int delta) {
        if (delta > 0) {
            this.score += delta;
            markModified();
        }
    }

    public boolean deductScore(int delta) {
        if (score >= delta && delta > 0) {
            this.score -= delta;
            markModified();
            return true;
        }
        return false;
    }
    // endregion

    // region 进度管理
    public void updateRepairProgress(int progress) {
        this.repairProgress = Math.min(100, Math.max(0, progress));
        markModified();
    }

    public void saveCheckpoint(int checkpointId, GameState state) {
        savePoints.put(checkpointId, state);
        this.currentCheckpoint = checkpointId;
        markModified();
    }
    // endregion

    // region 皮肤管理
    public boolean unlockSkin(String skinId) {
        if (unlockedSkins.add(skinId)) {
            markModified();
            return true;
        }
        return false;
    }

    public boolean changeSkin(String skinId) {
        if (unlockedSkins.contains(skinId)) {
            currentSkin = skinId;
            markModified();
            return true;
        }
        return false;
    }
    // endregion

    // region 装备管理
    public boolean purchaseEquipment(String equipmentId) {
        if (ownedEquipments.add(equipmentId)) {
            markModified();
            return true;
        }
        return false;
    }

    public boolean equip(String equipmentId) {
        if (ownedEquipments.contains(equipmentId)) {
            currentEquipment = equipmentId;
            markModified();
            return true;
        }
        return false;
    }
    // endregion

    // region 道具管理
    public void addItem(String itemId) {
        inventory.add(itemId);
        markModified();
    }

    public boolean useItem(String itemId) {
        return inventory.remove(itemId);
    }
    // endregion

    // 标记数据已修改
    private void markModified() {
        this.modified = true;
    }

    // region Getter方法
    public int getScore() {
        return score;
    }

    public int getRepairProgress() {
        return repairProgress;
    }

    public int getCurrentCheckpoint() {
        return currentCheckpoint;
    }

    public String getCurrentSkin() {
        return currentSkin;
    }

    public String getCurrentEquipment() {
        return currentEquipment;
    }

    public Set<String> getUnlockedSkins() {
        return Collections.unmodifiableSet(unlockedSkins);
    }

    public Set<String> getOwnedEquipments() {
        return Collections.unmodifiableSet(ownedEquipments);
    }

    public List<String> getInventory() {
        return Collections.unmodifiableList(inventory);
    }

    public GameState getSavePoint(int checkpointId) {
        return savePoints.get(checkpointId);
    }

    public boolean isModified() {
        return modified;
    }
    // endregion

    // 重置修改标记
    public void resetModifiedFlag() {
        this.modified = false;
    }

    // 深度克隆方法
    public PlayerData deepClone() {
        try {
            // 通过序列化/反序列化实现深度克隆
            java.io.ByteArrayOutputStream bos = new java.io.ByteArrayOutputStream();
            java.io.ObjectOutputStream out = new java.io.ObjectOutputStream(bos);
            out.writeObject(this);

            java.io.ByteArrayInputStream bis = new java.io.ByteArrayInputStream(bos.toByteArray());
            java.io.ObjectInputStream in = new java.io.ObjectInputStream(bis);
            return (PlayerData) in.readObject();
        } catch (Exception e) {
            throw new RuntimeException("Clone failed", e);
        }
    }
}